home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / XDME / Src / refs.c < prev    next >
C/C++ Source or Header  |  1996-09-26  |  15KB  |  765 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     $Id: refs.c 1.1 1994/08/09 13:52:48 digulla Exp digulla $
  5.  
  6.     DESCRIPTION
  7.     [v]ref [string]
  8.     Bringup a cross reference editor window.  The file [refpath]dme.refs
  9.     and dme.refs in the current directory are searched for the reference.
  10.     If found, the file specified is searched and the segment specified
  11.     loaded as a new file in a new (read-only) window.
  12.  
  13.     [v]ctags [string]
  14.     Bringup a cross definition editor window. The file [refpath]tags
  15.     and tags in the current directory are searched for the reference.
  16.     If found, the file specified is shown in a window, and the line
  17.     specified is visited.
  18.  
  19.  
  20.     NOTES
  21.  
  22.     BUGS
  23.  
  24.     TODO
  25.  
  26.     EXAMPLES
  27.  
  28.     SEE ALSO
  29.  
  30.     INDEX
  31.  
  32.     HISTORY
  33.     25. Nov 1992    ada created
  34.      3. Mar   93    null added Berkeley-Fix
  35.      1. Jan   94    null added autoinits
  36.      $Log: refs.c $
  37.  * Revision 1.1  1994/08/09  13:52:48  digulla
  38.  * Initial revision
  39.  *
  40.  * Revision 1.1  1994/08/09  13:49:24  digulla
  41.  * Initial revision
  42.  *
  43.  
  44. ******************************************************************************/
  45.  
  46. /**************************************
  47.         Includes
  48. **************************************/
  49. #include "defs.h"
  50.  
  51.  
  52. /**************************************
  53.         Globale Variable
  54. **************************************/
  55. Prototype void path_init   (void);
  56. Prototype void do_addpath  (void);
  57. Prototype void do_rempath  (void);
  58. Prototype void do_refctags (void);
  59. Prototype void do_ctags    (void);
  60. Prototype void do_refs       (void);
  61. Prototype int searchref    (char *, char *, char **, char **, long *, char **);
  62. Prototype int dirpart       (char *);
  63.  
  64. Prototype LIST PBase;
  65.  
  66. LIST    PBase;            /*  special XDME paths     */
  67.  
  68.  
  69. /**************************************
  70.       Interne Defines & Strukturen
  71. **************************************/
  72. typedef struct _PEN
  73. {
  74.     NODE    Node;
  75.     char    path[1];
  76. } PEN;
  77.  
  78.  
  79. /**************************************
  80.         Interne Variable
  81. **************************************/
  82.  
  83.  
  84. /**************************************
  85.        Interne Prototypes
  86. **************************************/
  87. static int strnspacecmp (const char * str1, const char * str2, int max);
  88.  
  89.  
  90. void path_init (void)
  91. {
  92.     PEN * pen;
  93.  
  94.     NewList ((struct List *)&PBase);
  95.  
  96.     if (pen = malloc (sizeof(PEN)))
  97.     {
  98.     *pen->path = 0;
  99.     pen->Node.ln_Name = pen->path;
  100.  
  101.     AddTail ((struct List *)&PBase, (struct Node *)pen);
  102.     }
  103. } /* path_init */
  104.  
  105.  
  106. static int strnspacecmp (const char * str1, const char * str2, int max)
  107. {
  108.     while (*str1 && max)
  109.     {
  110.     if (isspace (*str1))
  111.     {
  112.         if (!isspace (*str2))
  113.         break;
  114.  
  115.         while (isspace (*str1) && max) { str1 ++; max --; }
  116.  
  117.         if (!max)
  118.         break;
  119.  
  120.         while (isspace (*str2)) str2 ++;
  121.     }
  122.     else
  123.     {
  124.         if (*str1 != *str2)
  125.         break;
  126.  
  127.         str1 ++;
  128.         str2 ++;
  129.         max --;
  130.     }
  131.     }
  132.  
  133.     return (max ? *str1 - *str2 : 0);
  134. } /* strnspacecmp */
  135.  
  136.  
  137. /*
  138.  *  Special XDME paths for REF and CTAGS
  139.  */
  140.  
  141. void do_addpath (void)
  142. {
  143.     PEN * pen;
  144.     WORD  len = strlen (av[1]);
  145.  
  146.     for (pen = (PEN *)GetHead(&PBase); pen; pen=(PEN *)GetSucc((struct Node *)pen))
  147.     {
  148.     if (stricmp (av[1], pen->path) == 0)
  149.         return;
  150.     }
  151.  
  152.     if (pen = malloc (sizeof (PEN) + len))
  153.     strcpy (pen->path, av[1]);
  154.  
  155.     AddTail ((LIST *) & PBase, (NODE *) pen);
  156.  
  157.     pen->Node.ln_Name = pen->path;
  158. } /* do_addpath */
  159.  
  160.  
  161. void do_rempath (void)
  162. {
  163.     PEN * pen;
  164.  
  165.     for (pen = (PEN *)GetHead(&PBase); pen; pen = (PEN *)GetSucc((struct Node *)pen))
  166.     {
  167.     if (!stricmp (av[1], pen->path))
  168.     {
  169.         Remove ((NODE *) pen);
  170.         free (pen);
  171.     }
  172.     }
  173. } /* do_rempath */
  174.  
  175.  
  176. void do_refctags (void)
  177. {
  178.     char *av_bak[2];
  179.     BOOL requester;
  180.     BOOL title;
  181.  
  182.     av_bak[0] = av[0];
  183.     av_bak[1] = av[1];
  184.  
  185.     requester = globalflags.NoRequest;
  186.     title     = globalflags.Showtitle;
  187.  
  188.     globalflags.NoRequest = TRUE;
  189.     globalflags.Showtitle = FALSE;
  190.  
  191.     do_ctags ();
  192.  
  193.     if (globalflags.Abortcommand) {
  194.     globalflags.Abortcommand = 0;
  195.     do_refs ();
  196.     } /* if */
  197.  
  198.     globalflags.NoRequest = requester;
  199.     globalflags.Showtitle = title;
  200.  
  201.     if (globalflags.Abortcommand) {
  202.     char *str = ((av_bak[1] != NULL) ? (char *)av_bak[1] : current_word ());
  203.     if (!str[0])
  204.         error ("%s: No searchstring defined!\n", av_bak[0]);
  205.     else
  206.         error ("%s:\nCannot find anything about\n`%s'.", av_bak[0], str);
  207.     } /* if */
  208. } /* do_refctags */
  209.  
  210.  
  211. /*
  212.  *  Implement ctags
  213.  */
  214.  
  215. void do_ctags (void)
  216. {
  217.     char    str[256];
  218.     char    path[128];
  219.     char    buf[300];
  220.     char    sbuf[128];
  221.     WORD    xlen;
  222.     WORD    slen;
  223.     /* WORD    dbaselen; unused var */
  224.     BPTR    oldlock = CurrentDir (Ep->dirlock);
  225.     ED      * ed;
  226.     LONG    lineno = -1;
  227.  
  228.     if (av[1] != NULL)
  229.     {
  230.     strcpy (str, av[1]);
  231.     } else
  232.     {
  233.     strcpy (str, current_word ());
  234.     }
  235.     xlen = strlen (str);
  236.     if (!str[0]) {
  237.     error ("%s: No searchstring defined!\n", av[0]);
  238.     return;
  239.     } /* if */
  240.  
  241.     if (!Ep->iconmode)
  242.     title ("search tags");
  243.  
  244.     {
  245.     FILE * fi;
  246.     PEN  * pen;
  247.     WORD   j,
  248.            len;
  249.  
  250.     /*
  251.      *  Note: pen not used first pass and set to list head, so next
  252.      *  pass it will be the first element.
  253.      *
  254.      *  Note2:  The file path depends on several factors.  (1) tags in
  255.      *        'current' directory, use path to name of current window.
  256.      *        (2) tags in directory in XDME special path, use special
  257.      *        path.  (3) tag entry is a full path name, override
  258.      *        previous directories.
  259.      */
  260.  
  261.     mountrequest (0);
  262.  
  263.     for (pen=(PEN *)GetHead(&PBase); pen;
  264.                     pen=(PEN *)GetSucc((struct Node *)pen))
  265.     {
  266.         strcpy (path, pen->path);
  267.         AddPart (path, "tags", sizeof(path));
  268.         /* dbaselen = strlen (pen->path); dead assign */
  269.  
  270.         if (fi = fopen (path, "r"))
  271.         {
  272.         mountrequest (1);
  273.  
  274.         while ((len = xefgets (fi, buf, 128)) >= 0)
  275.         {
  276.             for (j = 0; buf[j] && buf[j] != ' '; ++j);
  277.  
  278.             if (j == 0 || buf[0] == '#')
  279.             continue;
  280.  
  281.             if (j == xlen && strncmp (str, buf, j) == 0)
  282.             {
  283.             while (buf[j] == ' ')
  284.                 ++j;
  285.  
  286.             /*
  287.              *  Extract the file name into str.  If the
  288.              *  filename does not contain an absolute path,
  289.              *  prepend it with such.
  290.              */
  291.             {
  292.                 char prep = 1;
  293.                 int i;
  294.  
  295.                 for (i = 0; buf[j] && buf[j] != ' '; ++i, ++j)
  296.                 {
  297.                 str[i] = buf[j];
  298.                 if (str[i] == ':')
  299.                     prep = 0;
  300.                 }
  301.  
  302.                 str[i] = 0;
  303.  
  304.                 if (prep)
  305.                 {
  306.                 char buf[256];
  307.  
  308.                 strcpy (buf, pen->path);
  309.                 AddPart (buf, str, sizeof(buf));
  310.  
  311.                 strcpy (str, buf);
  312.  
  313.                 /* i = strlen (str); dead assign */
  314.                 }
  315.             }
  316.  
  317.             fclose (fi);                        /* PATCH_NULL [10 Mar 1993] : moved 2 lines up */
  318.  
  319.             /* BERKELEY FIX: I have found a format in CTags */
  320.             /*    <tag> <file> <linenumber>        */
  321.             /* which is supported now            */
  322.             while (isspace(buf[j])) ++j;          /* PATCH_NULL [10 Mar 1993] : added */
  323.  
  324.             if (is_number (buf+j))              /* PATCH_NULL [10 Mar 1993] : added */
  325.             {                    /* PATCH_NULL [10 Mar 1993] : added */
  326.                 lineno = atol (buf+j)-1;        /* PATCH_NULL [10 Mar 1993] : added */
  327.             }                    /* PATCH_NULL [10 Mar 1993] : added */
  328.             else                    /* PATCH_NULL [10 Mar 1993] : added */
  329.             {                    /* PATCH_NULL [10 Mar 1993] : added */
  330.                 while (buf[j] && buf[j] != '^') /*  SEARCH ARG */
  331.                 ++j;
  332.  
  333.  
  334.                 if (buf[j] != '^')
  335.                 {
  336.                 error ("ctags:\nError in tags-file");
  337.                 goto done;
  338.                 }
  339.  
  340.                 ++j;    /* Skip ^ */
  341.  
  342.                 /* UN*X FIX: Dme works for Aztec ctags, which has the format:   */
  343.                 /*        <tag>   <file>  /^<pattern>                 */
  344.                 /* However, ctags under UN*X has the following format:        */
  345.                 /*        <tag>   <file>  /^<pattern>[$]/                */
  346.                 /* We just ignore the '$' and '/' so that both foramts work     */
  347.                 /* Thomas Rolfs 27/3/91                        */
  348.  
  349.                 {
  350.                 int i = 0;
  351.  
  352.                 while (buf[j] && buf[j] != '^' && buf[j] != '$'
  353.                         && buf[j] != '/' && buf[j] != '?')
  354.                 {
  355.                     sbuf[i++] = buf[j++];
  356.                 }
  357.  
  358.                 sbuf[i] = 0;
  359.                 }
  360.  
  361.                 /* End of fix.  */
  362.  
  363.                 slen = strlen (sbuf);
  364.             } /* if */                /* PATCH_NULL [10 Mar 1993] : added */
  365.  
  366.             if ((ed = finded (FilePart(str), 0)) == NULL) /* PATCH_NULL 20-07-94 added "FilePart" */
  367.             {
  368.                 strcpy (buf, "newwindow newfile `");
  369.                 strcat (buf, str);
  370.                 strcat (buf, "' viewmode on");
  371.                 do_command (buf);
  372.  
  373.                 /* remove path */
  374.                 strcpy (str, FilePart (str));
  375.  
  376.                 ed = finded (str, 0);
  377.             } else
  378.             {
  379.                 WindowToFront (ed->win);
  380.                 ActivateWindow (ed->win);
  381.             }
  382.  
  383.             if (ed == NULL)
  384.             {
  385.                 error ("ctags:\nunable to load file\n`%s'", str);
  386.                 goto done;
  387.             }
  388.  
  389.             switch_ed (ed);
  390.             text_cursor (0);
  391.  
  392.             if (lineno < 0)                                    /* PATCH_NULL [10 Mar 1993] : added */
  393.             {
  394.                 for (lineno = 0; lineno < ed->lines; ++lineno) /* PATCH_NULL [10 Mar 1993] : i -> lineno */
  395.                 {
  396.                 if (strnspacecmp (sbuf, ed->list[lineno], slen) == 0)
  397.                     break;
  398.                 }
  399.  
  400.                 if (lineno == ed->lines)
  401.                 {
  402.                 int i;
  403.  
  404.                 printf ("searching:\n");
  405.                 for (i=0; sbuf[i] && i<slen; i++)
  406.                 {
  407.                     printf ("%02x", sbuf[i]);
  408.                     if (i & 3 == 3)
  409.                     printf (" ");
  410.                 }
  411.                 printf ("\n");
  412.                 }
  413.             }
  414.  
  415.             sprintf (buf, "first goto %ld", lineno + 1);
  416.             do_command (buf);
  417.             text_cursor (1);    /* turn cursor on */
  418.  
  419.             goto done;
  420.             }
  421.         }
  422.  
  423.         fclose (fi);
  424.  
  425.         mountrequest (0);
  426.         }
  427.     }
  428.  
  429.     error ("ctags:\ntag `%s'\nnot found", str);
  430.  
  431.     mountrequest (1);
  432.     }
  433. done:
  434.     CurrentDir (oldlock);
  435. } /* do_ctags */
  436.  
  437.  
  438. /*
  439.  *  Implement references
  440.  */
  441.  
  442. void do_refs (void)
  443. {
  444.     static char str[MAXLINELEN];
  445.     static char tmpfile[128];
  446.     static char path[128];
  447.     char      * srch;
  448.     char      * file;
  449.     char      * estr;
  450.     long    len;
  451.     int     bcnt = 10;
  452.     WORD    slen,
  453.         elen;
  454.     FILE      * fi,
  455.           * fj;
  456.     WORD    tmph,
  457.         tmpw;
  458.     BPTR    oldlock = CurrentDir (Ep->dirlock);
  459.  
  460.     if (av[1] != NULL)
  461.     {
  462.     strcpy (str, av[1]);
  463.     }
  464.     else
  465.     strcpy (str, current_word ());
  466.  
  467.     if (!str[0]) {
  468.     error ("%s: No searchstring defined!\n", av[0]);
  469.     return;
  470.     } /* if */
  471.  
  472.  
  473.     strcpy (tmpfile, "t:ref_");
  474.     strncat (tmpfile, str, sizeof (tmpfile) - 32);
  475.  
  476.     title ("search .refs");
  477.  
  478.     {
  479.     PEN * pen;
  480.  
  481.     mountrequest (0);
  482.  
  483.     /* search all paths */
  484.     for (pen = (PEN *)GetHead(&PBase); pen; pen=(PEN *)GetSucc(pen))
  485.     {
  486.         strcpy (path, pen->path);
  487.         AddPart (path, "dme.refs", sizeof (path));
  488.  
  489.         if (searchref (path, str, &srch, &file, &len, &estr))
  490.         {
  491.         mountrequest (1);
  492.         goto found;
  493.         }
  494.     }
  495.  
  496.     error ("refs:\nReference `%s'\nnot found", str);
  497.     mountrequest (1);
  498.     goto done;
  499.     }
  500.  
  501. found:
  502.     title ("search file");
  503.     slen = strlen (srch);
  504.  
  505.     if (estr)
  506.     elen = strlen (estr);
  507.  
  508.     fi = fopen (file, "r");
  509.  
  510.     if (fi == NULL)
  511.     {        /*  try using path prefix   */
  512.     strcpy (str, path);
  513.     strcpy (str + strlen (str) - 8, file);
  514.     fi = fopen (str, "r");
  515.     }
  516.  
  517.     if (fi)
  518.     {
  519.     WORD  lenstr;
  520.  
  521.     if (srch[0] == '@' && srch[1] == '@')
  522.     {
  523.         fseek (fi, atoi (srch + 2), 0);
  524.         if ((lenstr = xefgets (fi, str, MAXLINELEN)) >= 0)
  525.         goto autoseek;
  526.     }
  527.  
  528.     while ((lenstr = xefgets (fi, str, MAXLINELEN)) >= 0)
  529.     {
  530.         if (strncmp (str, srch, slen) == 0)
  531.         {
  532. autoseek:
  533.         title ("load..");
  534.         if (fj = fopen (tmpfile, "w"))
  535.         {
  536.             tmph = 0;
  537.             tmpw = 0;
  538.  
  539.             do
  540.             {
  541.             if (lenstr > tmpw)
  542.                 tmpw = strlen (str);
  543.  
  544.             tmph ++;
  545.  
  546.             fputs (str, fj);
  547.             fputc ('\n', fj);
  548.  
  549.             if (estr && strncmp (str, estr, elen) == 0)
  550.                 break;
  551.  
  552.             len --;
  553.             }
  554.  
  555.             while ((lenstr = xefgets (fi, str, MAXLINELEN)) >= 0 && len);
  556.  
  557.             fclose (fj);
  558.  
  559.             if (tmph > 10)
  560.             tmph = 10;
  561.             if (tmpw > 80)
  562.             tmpw = 80;
  563.  
  564.             sprintf (str, "openwindow +0+0+%d+%d newfile %s viewmode on", (tmpw << 3) + 24, (tmph << 3) + 24, tmpfile);
  565.             do_command (str);
  566.             text_cursor (1);    /* turn cursor on */
  567.             unlink (tmpfile);
  568.         } else
  569.         {
  570.             error ("refs:\nUnable to open\n`%s'\nfor write", tmpfile);
  571.         }
  572.  
  573.         fclose (fi);
  574.         free (srch);
  575.         free (file);
  576.  
  577.         if (estr)
  578.             free (estr);
  579.  
  580.         goto done;
  581.         }
  582.         if (--bcnt == 0)
  583.         {  /* check break every so so  */
  584.         bcnt = 50;
  585.  
  586.         if (breakcheck ())
  587.             break;
  588.         }
  589.     }
  590.     fclose (fi);
  591.  
  592.     error ("refs:\nSearch for `%s'\nfailed", str);
  593.     } else
  594.     {
  595.     error ("refs:\nUnable to open\nsub document");
  596.     }
  597.  
  598.     free (srch);
  599.     free (file);
  600.  
  601.     if (estr)
  602.     free (estr);
  603. done:
  604.     CurrentDir (oldlock);
  605. } /* do_refs */
  606.  
  607.  
  608. /*
  609.  *  Reference file format:
  610.  *
  611.  *  `key' `lines' `file' `searchstring'
  612.  *
  613.  *  where `lines' can be a string instead ... like a read-until, otherwise
  614.  *  the number of lines to read from the reference.
  615.  */
  616.  
  617. int searchref (char * file, char * find, char ** psstr, char ** pfile, long * plines, char **pestr)
  618. {
  619.     FILE  * fi;
  620.     char    buf[MAXLINELEN];
  621.     char  * ptr,
  622.       * base;
  623.     char  * b1,
  624.       * b2,
  625.       * b3,
  626.       * b4;
  627.     char    quoted;
  628.  
  629.     /* WORD  findlen = strlen(find); TODO */
  630.  
  631.     if (fi = fopen (file, "r"))
  632.     {
  633.     while (xefgets (fi, (base = buf), MAXLINELEN) >= 0)
  634.     {
  635.         if (buf[0] == '#')
  636.         continue;
  637.  
  638.         ptr = breakout (&base, "ed, &b1);
  639.  
  640.         /* TODO if (ptr && *ptr && strncmp(ptr, find, findlen) == 0) */
  641.         if (ptr && *ptr && strcmp (ptr, find) == 0)
  642.         {
  643.         if (ptr = breakout (&base, "ed, &b2))
  644.         {
  645.             *pestr = NULL;
  646.             *plines = atoi (ptr);
  647.  
  648.             if (*plines == 0)
  649.             {
  650.             *pestr = (char *) malloc (strlen (ptr) + 1);
  651.             strcpy (*pestr, ptr);
  652.             }
  653.  
  654.             if (ptr = breakout (&base, "ed, &b3))
  655.             {
  656.             *pfile = (char *) malloc (strlen (ptr) + 1);
  657.             strcpy (*pfile, ptr);
  658.  
  659.             if (ptr = breakout (&base, "ed, &b4))
  660.             {
  661.                 *psstr = (char *) malloc (strlen (ptr) + 1);
  662.  
  663.                 strcpy (*psstr, ptr);
  664.                 fclose (fi);
  665.  
  666.                 if (b1)
  667.                 free (b1);
  668.                 if (b2)
  669.                 free (b2);
  670.                 if (b3)
  671.                 free (b3);
  672.                 if (b4)
  673.                 free (b4);
  674.  
  675.                 return (1);
  676.             }
  677.  
  678.             free (*pfile);
  679.  
  680.             if (b4)
  681.                 free (b4);
  682.             }
  683.  
  684.             if (pestr)
  685.             free (*pestr);
  686.             if (b3)
  687.             free (b3);
  688.         }
  689.  
  690.         if (b2)
  691.             free (b2);
  692.         }
  693.  
  694.         if (b1)
  695.         free (b1);
  696.     }
  697.  
  698.     fclose (fi);
  699.     }
  700.  
  701.     return (0);
  702. } /* searchref */
  703.  
  704.  
  705. int dirpart (char * str)
  706. {
  707.     WORD    i;
  708.  
  709.     for (i = strlen (str) - 1; i >= 0; --i)
  710.     {
  711.     if (str[i] == '/' || str[i] == ':')
  712.         break;
  713.     }
  714.  
  715.     return (i + 1);
  716. } /* dirpart */
  717.  
  718.  
  719.  
  720.  
  721. #if 0
  722.  
  723. static const
  724. struct CommandNode REF_Commands[] = {
  725.     {ENODE("addpath"),       1,        CF_VWM|CF_ICO, (FPTR)do_addpath  },
  726.     {ENODE("rempath"),       1, CF_VWM|CF_COK|CF_ICO, (FPTR)do_rempath  },
  727.     {ENODE("ctags"),         0,               CF_VWM, (FPTR)do_ctags    },
  728.     {ENODE("vctags"),        1,        CF_VWM|CF_ICO, (FPTR)do_ctags    },
  729.     {ENODE("ref"),           0,        CF_VWM|CF_ICO, (FPTR)do_refs     },
  730.     {ENODE("vref"),          1,        CF_VWM|CF_ICO, (FPTR)do_refs     },
  731.     {ENODE("refctags"),      0,        CF_VWM|CF_ICO, (FPTR)do_refctags },
  732.     {ENODE("vrefctags"),     1,        CF_VWM|CF_ICO, (FPTR)do_refctags }
  733. };
  734.  
  735. MK_AUTOINIT(REF_Init)
  736. {
  737.     int i;
  738.  
  739.     path_init();
  740.  
  741.     for (i = sizeof (REF_Commands)/sizeof (struct CommandNode) - 1;i >= 0; --i)
  742.     COM_Add (&REF_Commands[i]);
  743. } /* REF_Init */
  744.  
  745.  
  746. #if 0
  747. MK_AUTOEXIT(REF_Exit)
  748. {
  749.     int  i;
  750.     APTR lock;
  751.  
  752.     for (i = sizeof (REF_Commands)/sizeof (struct CommandNode) - 1; (i >= 0); DEC(i))
  753.     if (lock = COM_Lock (REF_Commands[i].cn_Name))
  754.         COM_Remove (lock);
  755. } /* REF_Exit */
  756.  
  757. #endif
  758.  
  759. #endif
  760.  
  761.  
  762. /******************************************************************************
  763. *****  ENDE refs.c
  764. ******************************************************************************/
  765.